package com.example.lin.gesture_detector;

import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener, View.OnTouchListener {

    private GestureDetector gestureDetector;
    private TextView tv_motion_event;
    private TextView tv_opration;
    private View view_test;

    public static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initGestureListener();
        initDoubleTapListener();

    }

    private void initDoubleTapListener() {
        gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
            /**
             * 用来判定该次点击是SingleTap而不是DoubleTap，如果连续点击两次就是DoubleTap手势，
             * 如果只点击一次，系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap，然后触发SingleTapConfirmed事件。
             * 触发顺序是：OnDown->OnsingleTapUp->OnsingleTapConfirmed
             * 关于onSingleTapConfirmed和onSingleTapUp的一点区别：
             * OnGestureListener有这样的一个方法onSingleTapUp，和onSingleTapConfirmed容易混淆。
             * 二者的区别是：onSingleTapUp，只要手抬起就会执行，而对于onSingleTapConfirmed来说，如果双击的话，则onSingleTapConfirmed不会执行。
             * @param e
             * @return
             */
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                tv_motion_event.setText("DoubleTap");
                return false;
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                tv_motion_event.setText("DoubleTapEvent");
                return false;
            }
        });
    }

    private void initGestureListener() {
        //该构造方法过时
//        GestureDetector gestureDetector1 = new GestureDetector(this);
        //推荐使用以下的构造方法，第一个参数是 上下文， 第二个参数是  GestureDetector.OnGestureListener
        gestureDetector = new GestureDetector(this, this);
        view_test.setOnTouchListener(this);
        view_test.setFocusable(true);
        view_test.setClickable(true);
        view_test.setLongClickable(true);
    }

    private void initView() {
        tv_motion_event = findViewById(R.id.tv_motion_event);
        tv_opration = findViewById(R.id.tv_operation);
        view_test = findViewById(R.id.view_test);
    }

    public static final int TV_MOTION_EVENT_NUM = 1;
    public static final int TV_OPERATION_NUM = 2;


    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case TV_MOTION_EVENT_NUM:
                    tv_motion_event.setTextColor(Color.GRAY);
                    tv_motion_event.setText(getResources().getString(R.string.tvMotionEventStr));
                    break;
                case TV_OPERATION_NUM:
                    tv_opration.setTextColor(Color.GRAY);
                    tv_opration.setText(getResources().getString(R.string.tvOperationStr));
                    break;
            }
            return false;
        }
    });


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    /**
     * 用户轻触屏幕，无论是否抬起手指，都会触发该方法，
     * 很少见到有用这个方法的，只要按下就会被触发，
     * 一定会影响到单击，长按等其他所有的触摸事件
     * 由1个MotionEvent ACTION_DOWN触发
     * 常用于一些流氓软件
     */
    @Override
    public boolean onDown(MotionEvent e) {
//        tv_motion_event.setBackgroundColor(Color.RED);
//        tv_motion_event.setText("onDown");
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM,4000);
        return false;
    }

    /**
     * 用户触摸屏幕一段时间未松开，有1个MotionEvent ACTION_DOWN 触发
     * onDown 是 无论是否松开都会触发，并不是我们常见的 单击方法
     *
     * @param e
     */
    @Override
    public void onShowPress(MotionEvent e) {
        tv_motion_event.setText("ShowPress");
        tv_motion_event.setTextColor(Color.RED);
        tv_opration.setText("MotionEvent" + e);
        Log.d(TAG, "onShowPress: " + e);
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM, 3000);
//        handler.sendEmptyMessageDelayed(TV_OPERATION_NUM, 3000);
    }

    /**
     * 用户点击屏幕后松开，由一个MotionEvent ACTION_UP 触发
     * 包含的操作有 一个点击和一个抬起，如果点击之后夹杂了其他的动作，这个方法不会被触发
     *
     * @param e
     * @return
     */
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        tv_motion_event.setTextColor(Color.BLUE);
        tv_motion_event.setText("SingleTapUp");
        tv_opration.setText("MotionEvent" + e);
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM, 3000);
//        handler.sendEmptyMessageDelayed(TV_OPERATION_NUM, 3000);
        return false;
    }

    /**
     * @param e1 The first down motion event that started the scrolling.
     * @param e2 The move motion event that triggered the current onScroll.
     * @param distanceX The distance along the X axis that has been scrolled since the last
     *              call to onScroll. This is NOT the distance between {@code e1}
     *              and {@code e2}.
     * @param distanceY The distance along the Y axis that has been scrolled since the last
     *              call to onScroll. This is NOT the distance between {@code e1}
     *              and {@code e2}.
     * @return true if the event is consumed, else false
     */

    /**
     * 用户按下触摸屏幕，并拖动，由一个 ACTION_DOWN,多个ACTION_MOVE触发
     *
     * @param e1        首次轻触屏幕的事件
     * @param e2        触发 该方法的 拖动事件
     * @param distanceX X 轴上移动的距离
     * @param distanceY Y 轴上移动的距离
     * @return
     */
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//        ViewGroup.LayoutParams lp = view_test.getLayoutParams();
//        lp.width = (int) (distanceX * 5);
//        lp.height = (int) (distanceY * 5);
//        view_test.setLayoutParams(lp);
        tv_motion_event.setText("Scroll");
        tv_opration.setText("e1 :" + e1 + "\n e2 :" + e2 + "distanceX :" + distanceX + "\n" + "distanceY :" + distanceY);
//        handler.sendEmptyMessageDelayed(TV_OPERATION_NUM,3000);
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM,3000);
        return false;
    }

    // 用户长按触摸屏，由多个MotionEvent ACTION_DOWN触发

    /**
     * Notified when a long press occurs with the initial on down {@link MotionEvent}
     * that trigged it.
     *
     * @param e The initial on down motion event that started the longpress.
     */
    @Override
    public void onLongPress(MotionEvent e) {
        tv_motion_event.setTextColor(Color.GREEN);
        tv_motion_event.setText("LongPress");
        tv_opration.setText("MotionEvent :" + e);
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM,3000);
//        handler.sendEmptyMessageDelayed(TV_OPERATION_NUM,3000);
    }

    // 用户按下触摸屏、快速移动后松开，由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发

    /**
     * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
     * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
     * the x and y axis in pixels per second.
     *
     * @param e1        The first down motion event that started the fling.
     * @param e2        The move motion event that triggered the current onFling.
     * @param velocityX The velocity of this fling measured in pixels per second
     *                  along the x axis.
     * @param velocityY The velocity of this fling measured in pixels per second
     *                  along the y axis.
     * @return true if the event is consumed, else false
     */
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        tv_motion_event.setText("Fling");
        tv_opration.setText("e1 :" + e1 + "\n e2 :" + e2 + "\n velocityX :" + velocityX + "\n velocityY :" + velocityY);
//        handler.sendEmptyMessageDelayed(TV_MOTION_EVENT_NUM,3000);
//        handler.sendEmptyMessageDelayed(TV_OPERATION_NUM,3000);
        return false;
    }
}